// Copyright 2007-2008 Rory Plaire (codekaizen@gmail.com)

using System;
using System.Runtime.InteropServices;

namespace NPack
{
    [StructLayout(LayoutKind.Sequential)]
    public struct DoubleComplex : IComparable<DoubleComplex>, IComparable<Double>, IComparable,
                                  IEquatable<DoubleComplex>, IEquatable<Double>
    {
        private readonly Double _real;
        private readonly Double _imaginary;

        public DoubleComplex(Double real, Double imaginary)
        {
            _real = real;
            _imaginary = imaginary;
        }

        public override String ToString()
        {
            return String.Format("{0:N8} + {1:N8}i", _real, _imaginary);
        }

        public override Int32 GetHashCode()
        {
            return _real.GetHashCode() ^ _imaginary.GetHashCode();
        }

        public Double Real
        {
            get { return _real; }
        }

        public Double Imaginary
        {
            get { return _imaginary; }
        }

        public static DoubleComplex operator -(DoubleComplex value)
        {
            return new DoubleComplex(-value._real, -value._imaginary);
        }

        public static DoubleComplex operator +(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real + rhs._real, lhs._imaginary + rhs._imaginary);
        }

        public static DoubleComplex operator +(DoubleComplex lhs, Double rhs)
        {
            return new DoubleComplex(lhs._real + rhs, lhs._imaginary);
        }

        public static DoubleComplex operator +(Double lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs + rhs._real, rhs._imaginary);
        }

        public static DoubleComplex operator -(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real - rhs._real, lhs._imaginary - rhs._imaginary);
        }

        public static DoubleComplex operator -(Double lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs - rhs._real, rhs._imaginary);
        }

        public static DoubleComplex operator -(DoubleComplex lhs, Double rhs)
        {
            return new DoubleComplex(lhs._real - rhs, lhs._imaginary);
        }

        public static DoubleComplex operator *(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real*rhs._real, lhs._imaginary*rhs._imaginary);
        }

        public static DoubleComplex operator /(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real/rhs._real, lhs._imaginary/rhs._imaginary);
        }

        public static explicit operator SingleComplex(DoubleComplex value)
        {
            return new SingleComplex((Single) value._real, (Single) value._imaginary);
        }

        #region IComparable<DoubleComplex> Members

        public Int32 CompareTo(DoubleComplex other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IComparable<Double> Members

        public Int32 CompareTo(Double other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IComparable Members

        public Int32 CompareTo(Object obj)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IEquatable<DoubleComplex> Members

        public Boolean Equals(DoubleComplex other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IEquatable<Double> Members

        public Boolean Equals(Double other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }
}